#include "sfmlWindow.h"

sf::Color colorById(int color) {
    switch (color) {
        case 0: return sf::Color(255, 20, 255, 225);
        case 1: return sf::Color(255, 20, 20, 225);
        case 2: return sf::Color(20, 255, 20, 225);
        case 3: return sf::Color(20, 20, 255);
        case 4: return sf::Color(255, 255, 20);
        case 5: return sf::Color(255, 255, 255);
        case 6: return sf::Color(20, 255, 255);
        case 7: return sf::Color(20, 20, 20);
        case 8: return sf::Color(100, 50, 170);
        case 9: return sf::Color(150, 100, 20);
    }

    return sf::Color(0, 0, 0);
}

SFMLWindow::SFMLWindow(QWidget* Parent, const QPoint& Position, const QSize& Size, unsigned int FrameTime) :
    QWidget       (Parent),
    myInitialized (false)
{
    // Setup some states to allow direct rendering into the widget
    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_NoSystemBackground);

    // Set strong focus to enable keyboard events to be received
    setFocusPolicy(Qt::StrongFocus);

    // Setup the widget geometry
    move(Position);
    resize(Size);

    // Setup the timer
    updTime = FrameTime;
    myTimer.setInterval(updTime);

    sf::Texture* shoottexture = new sf::Texture();
    if (!shoottexture->loadFromFile("shoot.png"))
        qDebug() << "Error loading shoot.png";
    shootSprite.setTexture(*shoottexture);

    sf::Texture* bgtext = new sf::Texture();
    if (!bgtext->loadFromFile("bg.png"))
        qDebug() << "Error loading bg.jpg";
    bgSprite.setTexture(*bgtext);
    bgSprite.setPosition(0, 0);
    bgSprite.setColor(sf::Color(170, 170, 170));

    my_color = 0;
    myTank = new Panzer(my_color);

    myTank->sprite.setPosition(my_color*16, my_color*15);
    myTank->hp = 100;

    while (tanks.size() > 0)
        tanks.pop_back();

    refreshed = true;
    connect(&refreshTimer, SIGNAL(timeout()), this, SLOT(refreshWeapon()));

    id_counter = 0;
}

#ifdef Q_WS_X11
    #include <Qt/qx11info_x11.h>
    #include <X11/Xlib.h>
#endif

void SFMLWindow::showEvent(QShowEvent *) {

    if (!myInitialized)
        {
            // Under X11, we need to flush the commands sent to the server to ensure that
            // SFML will get an updated view of the windows
            #ifdef Q_WS_X11
                XFlush(QX11Info::display());
            #endif

            // Create the SFML window with the widget handle
            RenderWindow::create(reinterpret_cast<sf::WindowHandle>(winId()));

            // Let the derived class do its specific stuff
            OnInit();

            // Setup the timer to trigger a refresh at specified framerate
            connect(&myTimer, SIGNAL(timeout()), this, SLOT(repaint()));
            myTimer.start(10);



            myInitialized = true;
        }
}
QPaintEngine* SFMLWindow::paintEngine() const {

    return 0;
}

void SFMLWindow::paintEvent(QPaintEvent*)
{
    //qDebug() << "paintEvent";
    // Let the derived class do its specific stuff
    OnUpdate();

    // Display on screen
    display();
}

void SFMLWindow::OnInit()
    {
        // Load the image


//        // Setup the sprite
//        mySprite.setTexture(myTexture);
//        //mySprite.setTextureRect(sf::IntRect(10, 10, 50, 30));
//        mySprite.setOrigin(46, 19);
//        mySprite.setColor(sf::Color(255, 20, 255, 225));
//        mySprite.setPosition(100, 100);
}

void SFMLWindow::OnUpdate() {

    checkInput();

    // Clear screen
    clear(sf::Color(0, 128, 0));

    draw(bgSprite);

    std::vector<Panzer*>::iterator it = tanks.begin();
    for(;it != tanks.end(); it++) {
        (*it)->render(this);
    }

    std::vector<shoot>::iterator sh = shoots.begin();
    for(;sh != shoots.end();) {
        shootSprite.setPosition((*sh).x, (*sh).y);
        shootSprite.setColor(colorById((*sh).color));
        draw(shootSprite);

        if (((*sh).x > WIDTH)||((*sh).y > HEIGHT)) { //ХИТРОТА
            sh = shoots.erase(sh);
        }
        else {
            sh++;
        }
    }
}

void SFMLWindow::checkInput() {

    if (myTank->hp > 0) {
        float x = sf::Mouse::getPosition(((sf::Window*)this)[0]).x - myTank->sprite.getPosition().x;
        float y = sf::Mouse::getPosition(((sf::Window*)this)[0]).y - myTank->sprite.getPosition().y;
        myTank->gunSprite.setRotation(180 + qAtan2(y, x)*360/(2*3.14));

        if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
            if (refreshed) {
                refreshed = false;
                refreshTimer.start(1000);
                attack();
            }
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
            myTank->sprite.rotate(-2);
        }
        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
            myTank->sprite.rotate(2);
        }

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
            myTank->sprite.setPosition(myTank->sprite.getPosition().x + qCos(myTank->sprite.getRotation()*2*3.14/360)*2,
                                 myTank->sprite.getPosition().y + qSin(myTank->sprite.getRotation()*2*3.14/360)*2);
        }
        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
            myTank->sprite.setPosition(myTank->sprite.getPosition().x - qCos(myTank->sprite.getRotation()*2*3.14/360)*2,
                                 myTank->sprite.getPosition().y - qSin(myTank->sprite.getRotation()*2*3.14/360)*2);
        }

        if (myTank->sprite.getGlobalBounds().left < 0)
            myTank->sprite.setPosition(myTank->sprite.getPosition().x + 2,
                                       myTank->sprite.getPosition().y);
        if (myTank->sprite.getGlobalBounds().left +  1.5*myTank->sprite.getGlobalBounds().width > WIDTH)
            myTank->sprite.setPosition(myTank->sprite.getPosition().x - 2,
                                       myTank->sprite.getPosition().y);

        if (myTank->sprite.getGlobalBounds().top < 0)
            myTank->sprite.setPosition(myTank->sprite.getPosition().x,
                                       myTank->sprite.getPosition().y + 2);
        if (myTank->sprite.getGlobalBounds().top +  2.5*myTank->sprite.getGlobalBounds().height > HEIGHT)
            myTank->sprite.setPosition(myTank->sprite.getPosition().x ,
                                       myTank->sprite.getPosition().y- 2);
    }

}


Panzer::Panzer(sf::Int16 col) {

    if (!texture.loadFromFile("panzer.png"))
        qDebug() << "Error loading file!1";

    if (!gunTexture.loadFromFile("gun.png"))
        qDebug() << "Error loading file!2";

    sprite.setTexture(texture);
    gunSprite.setTexture(gunTexture);

    sprite.setOrigin(46, 15);
    gunSprite.setOrigin(73, 13);

    color = col;

    sprite.setColor(colorById(color));
    gunSprite.setColor(colorById(color));

    //hp = 100;
}

void Panzer::render(sf::RenderWindow *w) {
    if (hp <= 0)
        sprite.setColor(sf::Color(139, 69, 19));
    else
        sprite.setColor(colorById(color));

    w->draw(sprite);
    gunSprite.setPosition(sprite.getPosition());
    w->draw(gunSprite);
}

void SFMLWindow::tankHere(tankInfo panzer) {

    Panzer* thisTank;

    std::vector<Panzer*>::iterator it = tanks.begin();
    for(;it != tanks.end(); it++) {
        thisTank = (*it);
        if (thisTank->color == panzer.color)
        {
            thisTank->hp = panzer.hp;
            thisTank->sprite.setPosition(panzer.x, panzer.y);
            thisTank->sprite.setRotation(panzer.alpha);
            thisTank->gunSprite.setPosition(panzer.x, panzer.y);
            thisTank->gunSprite.setRotation(panzer.beta);

            return;
        }
    }

    tanks.push_back(new Panzer(panzer.color));
    qDebug() << "new tank!";
}

void SFMLWindow::shootHere(shoot sh) {

    std::vector<shoot>::iterator it = shoots.begin();
    for(;it != shoots.end(); it++)
    {
        if (((*it).id == sh.id)&&((*it).color == sh.color))
        {
            (*it) = sh;
            return;
        }
    }

    shoots.push_back(sh);
    qDebug() << "new shoot!";
}

void SFMLWindow::changeColor(sf::Int16 col) {

    qDebug() << "color changed";

    my_color = col;
    myTank->sprite.setColor(colorById(col));
    myTank->gunSprite.setColor(colorById(col));
    myTank->color = my_color;
}

void SFMLWindow::start() {

    qDebug() << "start game";

    QTime t = QTime::currentTime();
    qsrand((uint)t.msec());

    myTank->sprite.setPosition(qrand()%500, qrand()%500);
    changeColor(my_color);

    while (tanks.size() > 0)
        tanks.pop_back();

    tanks.push_back(myTank);
    refreshed = true;

}


void SFMLWindow::leave() {

}


void SFMLWindow::refreshWeapon() {

    refreshTimer.stop();
    refreshed = true;
}

void SFMLWindow::attack() {

    shoot sh;
    short l = 80;
    sh.x = myTank->gunSprite.getPosition().x + l*qSin((myTank->gunSprite.getRotation()-90)*2*3.14/360);
    sh.y = myTank->gunSprite.getPosition().y - l*qCos((myTank->gunSprite.getRotation()-90)*2*3.14/360);
    sh.color = my_color;
    sh.alpha = myTank->gunSprite.getRotation();
    sh.id = id_counter++;

    shoots.push_back(sh);

    shootOut(sh);
}

